Socket 编程
Linux 中建立 TCP 连接的过程
在 Linux 中,TCP连接的建立使用了经典的三次握手(Three-Way Handshake)过程。在TCP协议栈中,涉及到多个方法和函数来实现连接的建立。以下是一些相关方法和函数的概述:
socket():该方法用于创建一个套接字(socket),并返回套接字文件描述符。套接字可以是流式套接字(SOCK_STREAM)或数据报套接字(SOCK_DGRAM)。
bind():该方法用于将套接字与特定的IP地址和端口号进行绑定。这是在服务器端监听特定IP地址和端口号的必要步骤。
listen():该方法用于将套接字设置为监听模式,使其可以接受连接请求。
accept():该方法用于接受客户端的连接请求,并创建一个新的套接字来处理与客户端的通信。
connect():该方法用于客户端发起连接请求,向服务器发送连接请求,并建立与服务器的连接。
send() 和 recv():这些方法用于在建立连接后,进行数据的发送和接收。send()用于发送数据,recv()用于接收数据。
close():该方法用于关闭套接字连接,释放相关资源。
以上是连接建立的基本方法和函数,其中 socket()、bind()、listen() 和 accept() 主要用于服务器端,而 connect() 则用于客户端。在Linux中,这些方法和函数是TCP连接建立过程中的关键组成部分。
整个过程如下图所示
Golang 中建立 TCP 连接的过程
服务器端的实现
package main
import (
"fmt"
"net"
"os"
)
func main() {
// 定义服务器监听地址和端口
listenAddr := "127.0.0.1:8080"
// 创建监听器
listener, err := net.Listen("tcp", listenAddr)
if err != nil {
fmt.Println("Error listening:", err)
os.Exit(1)
}
defer listener.Close()
fmt.Println("Server listening on", listenAddr)
// 接受客户端连接
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("Error accepting connection:", err)
os.Exit(1)
}
fmt.Println("Accepted connection from", conn.RemoteAddr().String())
// 处理客户端请求
go handleClient(conn)
}
}
// 处理客户端连接
func handleClient(conn net.Conn) {
defer conn.Close()
// 读取客户端发送的数据
buffer := make([]byte, 1024)
bytesRead, err := conn.Read(buffer)
if err != nil {
fmt.Println("Error reading data:", err)
return
}
request := string(buffer[:bytesRead])
fmt.Println("Received data from client:", request)
// 发送响应给客户端
response := "Hello, Client!"
_, err = conn.Write([]byte(response))
if err != nil {
fmt.Println("Error sending data:", err)
return
}
fmt.Println("Sent response to client:", response)
}
在此示例中,我们创建了一个TCP服务器,通过 net.Listen
函数监听指定的地址和端口。然后,我们在一个无限循环中接受客户端的连接。对于每个接受的连接,我们使用 go
关键字在新的 goroutine 中调用 handleClient
函数来处理客户端的请求。
在 handleClient
函数中,我们首先读取客户端发送的数据,然后打印出接收到的请求。接着,我们发送一个简单的响应给客户端。最后关闭与客户端的连接。
客户端的实现
package main
import (
"fmt"
"net"
"os"
)
func main() {
// 定义服务器地址和端口
serverAddr := "127.0.0.1:8080"
// 创建TCP连接
conn, err := net.Dial("tcp", serverAddr)
if err != nil {
fmt.Println("Error connecting to server:", err)
os.Exit(1)
}
defer conn.Close()
fmt.Println("Connected to server:", serverAddr)
// 在连接上发送数据
message := "Hello, Server!"
_, err = conn.Write([]byte(message))
if err != nil {
fmt.Println("Error sending data:", err)
return
}
fmt.Println("Sent data to server:", message)
// 接收来自服务器的响应
buffer := make([]byte, 1024)
bytesRead, err := conn.Read(buffer)
if err != nil {
fmt.Println("Error receiving data:", err)
return
}
response := string(buffer[:bytesRead])
fmt.Println("Received response from server:", response)
}